package com.android.newsreader;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.*;
import android.widget.TextView;
import android.widget.ListView;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.AdapterView.OnItemClickListener; 
import android.util.Log;

import java.net.URL;
import java.util.Iterator;
import java.util.List;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import android.content.Intent;

/**
* The activity class displays a list of news items
* read from an RSS Feed
*/
public class NewsReader extends Activity implements OnItemClickListener
{

	private RSSChannelProvider mDb4oHelper = null;
	
	public String mChosenRSSFeed = null;
	public RSSChannel mChosenChannel = null;
	public String mCategory = null;
	
	private RSSFeed mFeed = null;
	public RSSASyncTask retrieveFeeds = new RSSASyncTask(); 
	

	/**
	 *  Called when the activity is first created.
	 *   
	 * */
    public void onCreate(Bundle savedInstanceState) {
    	super.onCreate(savedInstanceState);
        setContentView(R.layout.news);
        
        // Opens database connection
        dbHelper();
       
        // Retrieves selected channel from intent passed from NewsHome class
        Intent startingIntent = getIntent();
        mCategory = startingIntent.getStringExtra("Category");
        mChosenChannel = (RSSChannel)startingIntent.getSerializableExtra(mCategory);
	    mChosenRSSFeed = mChosenChannel.getURL();
	    
        // Retrieve feed from with an ASync task to avoid freezing GUI thread
        retrieveFeeds = (RSSASyncTask)retrieveFeeds.execute((mChosenRSSFeed));
        
    }
    
    /**
     * Close database before exiting the application
     */
     @Override
     protected void onPause() {
          super.onDestroy();
          if (mDb4oHelper != null)
       	   mDb4oHelper.close();
     }
     
     /**
      * Open database when activity is resumed
      */
     @Override
 	  protected void onResume() {
 		
 		super.onResume();
 		dbHelper();
 	  }
    
    /**
     * Create RSSChannelProvider instance
     * 
     * Facilitates RSSChannel being queried from DB
     */
     private RSSChannelProvider dbHelper() {
         if (mDb4oHelper == null) {
            mDb4oHelper = RSSChannelProvider.getInstance(this);
            mDb4oHelper.db();
         }
         
         return mDb4oHelper;
     } 
    
    /**
 	 *  Creates an Options menu for the activity
 	 *  
 	 *  Menu Options:
 	 *  Edit RSS URL - Opens activity to input/amend the RSS URL
 	 *  Refresh - Invokes the RSS URL to refresh the news item
 	 *  Cancel - Tries to cancels refresh of RSS feed
 	 *  
 	 * */
    public boolean onCreateOptionsMenu(Menu menu) 
    {
    	super.onCreateOptionsMenu(menu);
    		
    	menu.add(0,0,0,getString(R.string.edit_rss));
    	menu.add(0,1,1,getString(R.string.refresh));
    	menu.add(0,2,2,getString(R.string.cancel));
    	
    	return true;
    }
    
    /**
 	 *  Sets an Options menu behaviour
 	 *  
 	 * */
    public boolean onOptionsItemSelected(MenuItem item){
        switch (item.getItemId()) {
        case 0:
        	// Opening InputFeedURL activity for selected channel
        	Intent itemintent = new Intent(this,InputFeedURL.class);
        	itemintent.putExtra("channel", mChosenChannel);
        	startActivity(itemintent);
        	
        	return true;
        case 1:
        	// Retrieving selected channel from db to ensure most
        	// recently updated url is used in refresh
        	List channelsFound = mDb4oHelper.findByName(this.mChosenChannel.getName());
        	
        	Iterator channelsIter = channelsFound.iterator();
        	int i = 0;
        	while (channelsIter.hasNext()) {
        		RSSChannel channel = (RSSChannel)channelsIter.next();
        		if (channel.getCategory().equalsIgnoreCase(mCategory)) {
        			mChosenChannel = channel;
        		}	
        	}
        	
        	mChosenRSSFeed = mChosenChannel.getURL();
        	
        	retrieveFeeds = new RSSASyncTask(); 
        	retrieveFeeds.execute((mChosenRSSFeed));
            return true;
    	case 2:
    		// invoke cancel on the ASyncTask to attempt to cancel
    		// RSS feed refresh
    		boolean result = this.retrieveFeeds.cancel(true);
    		return true;
    	}
        return false;
    }
    
    
    /**
 	 *  Updates item list in this activity with items from RSS feed
 	 *  
 	 * */
    private void updateDisplay()
    {
        TextView feedtitle = (TextView) findViewById(R.id.feedtitle);
        TextView feedpubdate = (TextView) findViewById(R.id.feedpubdate);
        ListView itemlist = (ListView) findViewById(R.id.itemlist);
  
        
        if (mFeed == null)
        {
        	feedtitle.setText(getString(R.string.none_avail));
        	return;
        }
        
        feedtitle.setText(mFeed.getTitle());
        feedpubdate.setText(mFeed.getPubDate());

        ArrayAdapter<RSSItem> adapter = new ArrayAdapter<RSSItem>(this,android.R.layout.simple_list_item_1,mFeed.getAllItems());

        itemlist.setAdapter(adapter);
        
        itemlist.setOnItemClickListener(this);
        
        itemlist.setSelection(0);
        
    }
    
    /**
 	 *  Set behaviour for list item clicks
 	 *  Will open the ShowStory activity for selected item
 	 *  
 	 * */
     public void onItemClick(AdapterView parent, View v, int position, long id)
     {
    	 Intent itemintent = new Intent(this,ShowStory.class);
         
    	 Bundle b = new Bundle();
    	 b.putString("title", mFeed.getItem(position).getTitle());
    	 b.putString("description", mFeed.getItem(position).getDescription());
    	 b.putString("link", mFeed.getItem(position).getLink());
    	 b.putString("pubdate", mFeed.getItem(position).getPubDate());
    	 b.putInt("source", 1);
    	 
    	 itemintent.putExtra("android.intent.extra.INTENT", b);
         
    	 startActivity(itemintent);
     }
     
     /**
     *  Private class for creating ASync Tasks
     *  
     *  This class will retrieve RSS feeds from internet 
     *  in the background, this allows the user to continue to 
     *  interact with the GUI while this task is underway
     */
     private class RSSASyncTask extends AsyncTask<String, Integer, RSSFeed> {
    	 	
    	    /**
    	     *  Method invoked before background task is started
    	     *  
    	     *  Creates progress icon in Title bar 
    	     * */
    	    protected void onPreExecute(){
    	    	getParent().setProgressBarIndeterminateVisibility(true);
    	    }
    	 
    	 	
    	    /**
    	     *  Method which invokes background task 
    	     *  
    	     *  Retrieves RSS feeds
    	     *  
    	     */
    		@Override
    		protected RSSFeed doInBackground(String... urls) {
    			
    			int count = urls.length;
    			
    	        for (int i = 0; i < count; i++) {
    	             mFeed = getFeed(urls[i]);
    	         }
    	         
    			return mFeed;
    		}
    		
    		protected void onProgressUpdate(Integer... progress) {
    	        setProgress(progress[0]);
    	    }

    		/**
    	     *  Method invoked after background task has finished
    	     *  
    	     *  Stops progress icon in Title bar
    	     *  Updates NewsReader activity 
    	     * */
    	    protected void onPostExecute(RSSFeed result) {
    	    	// display UI
    	    	getParent().setProgressBarIndeterminateVisibility(false);
    	        updateDisplay();
    	    }
    	    
    	    /**
    	     *  Method for retrieving RSS feeds
    	     *  
    	     *  Sourced from:
    	     *  	http://www.ibm.com/developerworks/xml/tutorials/x-androidrss/section2.html
    	     * */
    	    private RSSFeed getFeed(String urlToRssFeed)
    	    {
    	    	try
    	    	{
    	    		// setup the url
    	    	   URL url = new URL(urlToRssFeed);

    	           // create the factory
    	           SAXParserFactory factory = SAXParserFactory.newInstance();
    	           // create a parser
    	           SAXParser parser = factory.newSAXParser();

    	           // create the reader (scanner)
    	           XMLReader xmlreader = parser.getXMLReader();
    	           
    	           // instantiate our handler
    	           RSSHandler theRssHandler = new RSSHandler();
    	           // assign our handler
    	           xmlreader.setContentHandler(theRssHandler);
    	           
    	           // get our data via the url class
    	           InputSource is = new InputSource(url.openStream());
    	           // perform the synchronous parse           
    	           xmlreader.parse(is);
    	           // get the results - should be a fully populated RSSFeed instance, or null on error
    	           return theRssHandler.getFeed();
    	    	}
    	    	catch (Exception ee)
    	    	{
    	    		// if we have a problem, simply return null
    	    		return null;
    	    	}
    	    }

    	}
     
     
    
}